use serde::{Serialize, Deserialize};
use std::fs;
use std::path::Path;
 

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct FileEntry {
  name: String,
  is_dir: bool,
  size: u64,
  modified: u64,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(tag = "type")]
pub enum ProviderConfig {
    OpenAI {
        id: String,
        name: String,
        api_key: String,
        model: String,
    },
}

#[derive(Serialize, Deserialize, Debug, Clone, Default)]
pub struct AppConfig {
    pub active_provider_id: Option<String>,
    pub providers: Vec<ProviderConfig>,
}



#[tauri::command]
fn list_directory(path: String) -> Result<Vec<FileEntry>, String> {
    let mut entries = Vec::new();
    let path = Path::new(&path);

    if !path.exists() {
        return Err(format!("Path does not exist: {}", path.display()));
    }

    if !path.is_dir() {
        return Err(format!("Path is not a directory: {}", path.display()));
    }

    for entry in fs::read_dir(path).map_err(|e| e.to_string())? {
        let entry = entry.map_err(|e| e.to_string())?;
        let path = entry.path();
        let metadata = entry.metadata().map_err(|e| e.to_string())?;

        let name = path.file_name()
            .unwrap_or_default()
            .to_string_lossy()
            .to_string();

        let modified = metadata.modified()
            .map_err(|e| e.to_string())?
            .duration_since(std::time::UNIX_EPOCH)
            .map_err(|e| e.to_string())?
            .as_secs();

        entries.push(FileEntry {
            name,
            is_dir: metadata.is_dir(),
            size: metadata.len(),
            modified,
        });
    }

    // Sort entries by modification time, newest first.
    entries.sort_by(|a, b| b.modified.cmp(&a.modified));

    Ok(entries)
}

#[tauri::command]
fn create_folder(path: String) -> Result<(), String> {
    fs::create_dir(path).map_err(|e| e.to_string())
}

#[tauri::command]
fn delete_item(path: String) -> Result<(), String> {
    let path = Path::new(&path);
    if path.is_dir() {
        fs::remove_dir_all(path).map_err(|e| e.to_string())
    } else {
        fs::remove_file(path).map_err(|e| e.to_string())
    }
}

#[tauri::command]
fn rename_item(old_path: String, new_path: String) -> Result<(), String> {
    fs::rename(old_path, new_path).map_err(|e| e.to_string())
}

#[tauri::command]
fn get_config(store: tauri::State<tauri_plugin_store::Store<tauri::Wry>>) -> Result<AppConfig, String> {
    match store.get("app_config") {
        Some(config) => Ok(serde_json::from_value(config.clone()).unwrap_or_default()),
        None => Ok(AppConfig::default()),
    }
}

#[tauri::command]
fn save_config(config: AppConfig, store: tauri::State<tauri_plugin_store::Store<tauri::Wry>>) -> Result<(), String> {
    store.set("app_config".to_string(), serde_json::to_value(config).unwrap());
    store.save().map_err(|e| e.to_string())?;
    Ok(())
}


#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .plugin(tauri_plugin_opener::init())
        .plugin(tauri_plugin_store::Builder::new().build())
        .plugin(tauri_plugin_fs::init())
        .plugin(tauri_plugin_dialog::init())
        .invoke_handler(tauri::generate_handler![list_directory, create_folder, delete_item, rename_item, get_config, save_config])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}
